home *** CD-ROM | disk | FTP | other *** search
- ;_ macros.asm
- ; Copyright (C) 1985-1991 by Walter Bright
- ; All Rights Reserved
- ; Modified for COFF and ELF support by David Bustin
- ; $Revision: 1.1.1.1 $
-
- ifdef _WIN32
- ifndef __NT__
- __NT__ equ 1
- endif
- endif
-
- ifndef M_I386
-
- ifdef _WINDOWS
- extrn MESSAGEFATALERROR : far
- endif
-
- ; modified for RATIONAL support by P Murray, April 1990
- ; define DOS16RM for protected mode programs
-
- ; Determine which memory model we are assembling for. For .COM files,
- ; force S model.
-
- ifdef DOS16RM
- ifndef I8086L
- %out Only L model supported with RATIONAL DOS Extender.
- end
- endif
- else
- ifdef I8086T
- I8086S equ 1
- else
- ifndef I8086S
- ifndef I8086M
- ifndef I8086C
- ifndef I8086L ;if none of the memory models are defined
- ifndef I8086V
- I8086S equ 1 ;default to S model
- endif ;I8086V
- endif ;I8086L
- endif ;I8086C
- endif ;I8086M
- endif ;I8086S
- endif ;I8086T
- endif ;DOS16RM
-
- ifdef __OS2__
- .286C
- endif
-
-
- ifdef DOS16RM
- .286P
- endif
-
- ifndef I386
- I386 equ 0
- endif
-
- ;Decide if SI and DI are saved across function calls
- SAVESIDI equ 1 ;1 means SI and DI are saved across functions
-
- if 0 ;Lattice conventions no longer supported
- MSC equ 1 ;ifdef means use Microsoft C calling conventions
- ;ifndef means use Lattice
- endif
-
- ; Macros to bracket data segment stuff.
-
- ifndef STARTUP
- begdata macro
-
- ifdef DOS16RM
- ;Segment so we can find the start of DGROUP
-
- NULL segment para public 'BEGDATA' ;Note PARAGRAPH alignment
- NULL ends
- endif
-
- _DATA segment word public 'DATA'
- _DATA ends
- CONST segment word public 'CONST'
- CONST ends
- _BSS segment word public 'BSS'
- _BSS ends
- ifdef DOS16RM
- DGROUP group NULL,_DATA,CONST,_BSS
- else
- DGROUP group _DATA,CONST,_BSS
- endif
- _DATA segment
- assume ds:DGROUP
- endm
- endif ; STARTUP
-
- enddata macro
- _DATA ends
- endm
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Macros specific to each memory model in an attempt to make it easier
- ; to write memory model independent code.
- ; begcode,endcode Use to bracket code sections
- ; P Offset on BP to first argument on stack
- ; (excluding any local variables)
- ; SPTR 1 if small data model
- ; LPTR 1 if large pointers (large data)
- ; LCODE 1 if large code model
- ; ESeqDS 1 if ES == DS at all times
- ; SSeqDS 1 if SS == DS at all times
- ; SIZEPTR # of bytes in a pointer
- ; func Declare a function as NEAR or FAR
- ; callm Call function as NEAR or FAR
-
- ;;;;;;;;;;;;;; SMALL MEMORY MODEL ;;;;;;;;;;;;;;;;;
- ifdef I8086S
- begcode macro module
- _TEXT segment word public 'CODE'
- assume cs:_TEXT
- endm
-
- endcode macro module
- _TEXT ENDS
- endm
-
- P equ 4 ; Offset of start of parameters on the stack frame
- SPTR equ 1
- LPTR equ 0
- LCODE equ 0
- ESeqDS equ 0
- SSeqDS equ 1
- SIZEPTR equ 2 ; Size of a pointer
-
- p_func macro name
- name proc near
- endm
-
- p_endp macro name
- name endp
- endm
-
- callp macro name
- call near ptr name
- endm
-
- func macro name
- _&name proc near
- ifndef name
- name equ _&name
- endif
- endm
-
- callm macro name
- call near ptr _&name
- endm
- endif
-
- ;;;;;;;;;;;;;;;;; MEDIUM MEMORY MODEL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ifdef I8086M
- begcode macro module
- module&_TEXT segment para public 'CODE'
- assume cs:module&_TEXT
- endm
-
- endcode macro module
- module&_TEXT ends
- endm
-
- P equ 6 ; Offset of start of parameters on the stack frame
- SPTR equ 1
- LPTR equ 0
- LCODE equ 1
- ESeqDS equ 0
- SSeqDS equ 1
- SIZEPTR equ 2
-
- p_func macro name
- name proc far
- endm
-
- p_endp macro name
- name endp
- endm
-
- callp macro name
- call far ptr name
- endm
-
- func macro name
- _&name proc far
- ifndef name
- name equ _&name
- endif
- endm
-
- callm macro name
- call far ptr _&name
- endm
- endif
-
- ;;;;;;;;;;;;;;;;; COMPACT MEMORY MODEL ;;;;;;;;;;;;;;
-
- ifdef I8086C
- begcode macro module
- _TEXT segment word public 'CODE'
- assume cs:_TEXT
- endm
-
- endcode macro module
- _TEXT ends
- endm
-
- P equ 4 ; Offset of start of parameters on the stack frame
- SPTR equ 0
- LPTR equ 1
- LCODE equ 0
- ESeqDS equ 0
- SSeqDS equ 0
- SIZEPTR equ 4
-
- p_func macro name
- name proc near
- endm
-
- p_endp macro name
- name endp
- endm
-
- callp macro name
- call near ptr name
- endm
-
- func macro name
- _&name proc near
- ifndef name
- name equ _&name
- endif
- endm
-
- callm macro name
- call near ptr _&name
- endm
- endif
-
- ;;;;;;;;;;;;;;;; LARGE MEMORY MODEL ;;;;;;;;;;;;;;;;;;;
-
- ifdef I8086L
- begcode macro module
- module&_TEXT segment para public 'CODE'
- assume cs:module&_TEXT
- endm
-
- endcode macro module
- module&_TEXT ends
- endm
-
- P equ 6 ; Offset of start of parameters on the stack frame
- SPTR equ 0
- LPTR equ 1
- LCODE equ 1
- ESeqDS equ 0
- SSeqDS equ 0
- SIZEPTR equ 4
-
- p_func macro name
- name proc far
- endm
-
- p_endp macro name
- name endp
- endm
-
- callp macro name
- call far ptr name
- endm
-
- func macro name
- _&name proc far
- ifndef name
- name equ _&name
- endif
- endm
-
- callm macro name
- call far ptr _&name
- endm
- endif
-
- ;Macros to replace public, extrn, and endp for C-callable assembly routines,
- ; and to define labels: c_label defines labels,
- ; c_public replaces public, c_extrn replaces extrn, and c_endp replaces endp
-
- c_name macro name
- name equ _&name
- endm
-
- c_label macro name
- _&name:
- endm
-
- c_public macro a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
- ifnb <a> ;;Check for blank argument
- public _&a
- a equ _&a
- ifnb <b>
- c_public b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
- endif
- endif
- endm
-
- c_extrn macro a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
- ifnb <a> ;;Check for blank argument
- extrn _&a:b
- a equ _&a
- ifnb <c>
- c_extrn c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
- endif
- endif
- endm
-
- c_endp macro name
- _&name ENDP
- endm
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Define function ctor as a static constructor
- static_ctor macro ctor
- if LCODE
- XIFB segment word public 'DATA'
- XIFB ends
- XIF segment word public 'DATA'
- dd ctor
- XIF ends
- XIFE segment word public 'DATA'
- XIFE ends
- else
- XIB segment word public 'DATA'
- XIB ends
- XI segment word public 'DATA'
- dw ctor
- XI ends
- XIE segment word public 'DATA'
- XIE ends
- endif
- endm
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Define function ctor as a static destructor
- static_dtor macro dtor
- if LCODE
- XCFB segment word public 'DATA'
- XCFB ends
- XCF segment word public 'DATA'
- dd dtor
- XCF ends
- XCFE segment word public 'DATA'
- XCFE ends
- else
- XCB segment word public 'DATA'
- XCB ends
- XC segment word public 'DATA'
- dw dtor
- XC ends
- XCE segment word public 'DATA'
- XCE ends
- endif
- endm
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Other more or less useful macros
- ; Commented out ones are obsolete
-
- ;setESeqDS macro ;set ES == DS, if not already true
- ; ife ESeqDS
- ; push DS
- ; pop ES
- ; endif
- ; endm
-
- .push macro list
- irp arg,<list>
- push arg
- endm
- endm
-
- .pop macro list
- irp arg,<list>
- pop arg
- endm
- endm
-
- _push macro list
- irp arg,<list>
- push arg
- endm
- endm
-
- _pop macro list
- irp arg,<list>
- pop arg
- endm
- endm
-
- ; Macros to save and restore regs destroyed by a function
-
- .save macro list
- if SAVESIDI
- irp arg,<list>
- push arg
- endm
- endif
- endm
-
- .restore macro list
- if SAVESIDI
- irp arg,<list>
- pop arg
- endm
- endif
- endm
-
- _save macro list
- if SAVESIDI
- irp arg,<list>
- push arg
- endm
- endif
- endm
-
- _restore macro list
- if SAVESIDI
- irp arg,<list>
- pop arg
- endm
- endif
- endm
-
- ; Macros to save and restore ES, but only if ESeqDS is 1.
- ;pushES macro
- ; if ESeqDS
- ; push ES
- ; endif
- ; endm
- ;
- ;popES macro
- ; if ESeqDS
- ; pop ES
- ; endif
- ; endm
-
- clr macro list ;clear a register
- irp reg,<list>
- xor reg,reg
- endm
- endm
-
- tst macro reg
- test reg,reg
- endm
-
- jmps macro lbl
- jmp short lbl
- endm
-
- if @Version lt 600
- ;For compatibility with MASM 5.10
- .if macro arg1,cond,arg2,lbl
- cmp arg1,arg2
- j&cond lbl
- endm
-
- endif
-
- _if macro arg1,cond,arg2,lbl
- cmp arg1,arg2
- j&cond lbl
- endm
-
- ;sob macro arg,lbl
- ; ifidn <arg>,<CX>
- ; loop lbl
- ; else
- ; dec arg
- ; jnz lbl
- ; endif
- ; endm
-
-
- ifdef _WINDOWS
- extrn DOS3CALL : far
- endif
-
- ifndef nobdos
- bdos macro func
- ifnb <func>
- mov AH,func
- endif
- ifndef _WINDOWS
- int 21h
- else
- call DOS3CALL
- endif
- endm
-
- dpmi macro func
- ifnb <func>
- mov AX,func
- endif
- int 31h
- endm
- else
- __bdos macro func
- ifnb <func>
- mov AH,func
- endif
- ifndef _WINDOWS
- int 21h
- else
- call DOS3CALL
- endif
- endm
-
- __dpmi macro func
- ifnb <func>
- mov AX,func
- endif
- int 31h
- endm
- endif
-
- .retf macro val ;force assembler to build a far return
- ifnb <val>
- db 0CAh
- dw val
- else
- db 0CBh
- endif
- endm
-
- _retf macro val ;force assembler to build a far return
- ifnb <val>
- db 0CAh
- dw val
- else
- db 0CBh
- endif
- endm
-
- ; Sometimes MASM ignores my segment overrides.
- segES macro
- db 26h
- endm
-
- ; 32 bit negate
- neg32 macro reg1,reg2
- neg reg1
- neg reg2
- sbb reg1,0
- endm
-
- ; Push immediate (reg is for scratch)
- pushi macro reg,value
- if 0
- push value ;for 286 code generation only
- else
- mov reg,value
- push reg
- endif
- endm
-
- ; Inc/dec BP if I8086V memory model
- incBP macro
- ifdef I8086V
- inc BP
- endif
- endm
-
- decBP macro
- ifdef I8086V
- dec BP
- endif
- endm
-
- WINENTER macro
- ifdef _WINDOWS
- ifndef I8086S
- ifndef I8086C
- inc BP
- endif
- endif
- endif
- push BP
- mov BP,SP
- endm
-
- WINLEAVE macro
- pop BP
- ifdef _WINDOWS
- ifndef I8086S
- ifndef I8086C
- dec BP
- endif
- endif
- endif
- endm
-
- WINENTER_NF macro
- ifdef _WINDOWS
- ifndef I8086S
- ifndef I8086C
- inc BP
- push BP
- mov BP,SP
- endif
- endif
- endif
- endm
-
- WINLEAVE_NF macro
- ifdef _WINDOWS
- ifndef I8086S
- ifndef I8086C
- pop BP
- dec BP
- endif
- endif
- endif
- endm
-
- else ;M_I386
-
- .386P
- .387
-
- ifdef DOS386
- SEG_1ST_MEG equ 034h ;Selector of 1st Mbyte used by MSDOS
- SEG_SCREEN equ 01ch ;Selector for the video memory.
- SEG_PSP equ 024H ;PSP selector.
- SEG_DGROUP equ 014H ;DGROUP selector.
- SEG_ENV equ 02cH ;Selector of environment string.
-
- OMF equ 1
- COFF equ 0
- ELF equ 0
- _FLAT equ 0 ;FLAT memory model
- _STDCALL equ 0 ;default to _stdcall
- _RETST0 equ 0 ;return floating point results in ST0
- endif ;DOS386
-
- ifdef X386
- _FLAT equ 0
- _STDCALL equ 0
- _RETST0 equ 0
- endif
-
- ifdef __OS2__
- OMF equ 1
- COFF equ 0
- ELF equ 0
- _FLAT equ 1 ;FLAT memory model
- _STDCALL equ 1
- _RETST0 equ 1
- _INLINE_8087 equ 1 ;defined if we always generate inline 8087 code
- endif
-
- ifdef __NT__
- OMF equ 1
- COFF equ 0
- ELF equ 0
- _FLAT equ 1
- _STDCALL equ 0
- _RETST0 equ 1
- ;_NOCTOR equ 1 ;defined if no static constructors/destructors supported
- _INLINE_8087 equ 1 ;defined if we always generate inline 8087 code
- LONGDOUBLE equ 1 ;defined if memory model supports 80 bit long doubles
- endif
-
- ifdef M_XENIX
- OMF equ 1 ;Set to non-zero if OMF object format.
- COFF equ 0 ;Set to non-zero if COFF object format.
- ELF equ 0
- _FLAT equ 0
- _STDCALL equ 0
- _RETST0 equ 0
- endif
-
- ifdef M_UNIX
- ifndef OMF
- OMF equ 0 ;Set to non-zero if OMF object format.
- endif
- ifdef M_ELF
- ifndef ELF
- ELF equ 1 ;Set to non-zero if ELF object format.
- endif
- ifndef COFF
- COFF equ 0 ;Set to non-zero if COFF object format.
- endif
- else ;M_ELF
- ifndef ELF
- ELF equ 0 ;Set to non-zero if ELF object format.
- endif
- ifndef COFF
- COFF equ 1 ;Set to non-zero if COFF object format.
- endif
- endif ;M_ELF
- _FLAT equ 0
- _STDCALL equ 0
- _RETST0 equ 0
- endif
-
- .ERRNZ OMF AND COFF AND ELF
- .ERRE OMF OR COFF OR ELF
-
- I386 equ 1
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Macros specific to each memory model in an attempt to make it easier
- ; to write memory model independent code.
- ; begcode,endcode Use to bracket code sections
- ; begdata,enddata Use to bracket data sections
- ; begrcode,endrcode Use to bracket real mode code sections
- ; begrdata,endrdata Use to bracket real mode data sections
- ; (Pharlap DOS386 only)
- ; P Offset on EBP to first argument on stack
- ; Assuming EBP was pushed.
- ; PS Offset on ESP to first argument on stack
- ; Assuming nothing was pushed on the stack.
- ; ESeqDS 1 if ES == DS at all times
- ; FSeqDS 1 if FS == DS at all times
- ; GSeqDS 1 if GS == DS at all times
- ; SSeqDS 1 if SS == DS at all times
- ; SIZEPTR # of bytes in a pointer
- ; func Declare a function as NEAR or FAR
- ; callm Call function as NEAR or FAR
- ; LPTR Large data model?
- ; SPTR Small data model?
-
-
- ;Macro for start and end of real mode code segment.
-
- begcode_16 macro
- __X386_CODESEG_16 segment para use16 public 'CODE'
- assume ds:__X386_GROUP_16
- assume cs:__X386_CODESEG_16
- endm
-
- endcode_16 macro
- __X386_CODESEG_16 ends
- endm
-
- begcode macro module
- if _FLAT
- _TEXT segment para use32 public 'CODE'
- assume CS:FLAT,DS:FLAT,SS:FLAT
- else
- _TEXT segment dword public 'CODE'
- assume CS:_TEXT
- endif
- endm
-
- endcode macro module
- _TEXT ENDS
- endm
-
- begdata macro
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Set up segments for data
- ; Regular initialized data goes in _DATA
-
- _DATA segment dword public 'DATA'
- _DATA ends
-
- ifndef _NOCTOR
- ;Function pointers to constructors
- if OMF
- XIFCB segment dword public 'DATA'
- XIFCB ends
- XIFU segment dword public 'DATA'
- XIFU ends
- XIFL segment dword public 'DATA'
- XIFL ends
- XIFM segment dword public 'DATA'
- XIFM ends
- XIFCE segment dword public 'DATA'
- XIFCE ends
- XIB segment dword public 'DATA'
- XIB ends
- XI segment dword public 'DATA'
- XI ends
- XIE segment dword public 'DATA'
- XIE ends
-
- ;Function pointers to destructors
- XCB segment dword public 'DATA'
- XCB ends
- XC segment dword public 'DATA'
- XC ends
- XCE segment dword public 'DATA'
- XCE ends
-
- ;Constant data, such as switch tables, go here.
-
- CONST segment dword public 'CONST'
- CONST ends
- endif
- ;Segment for uninitialized data. This is set to 0 by the startup code/OS,
- ;so it does not consume room in the executable file.
-
- _BSS segment dword public 'BSS'
- _BSS ends
-
- if OMF
- ;Function pointers to destructors
- XOB segment dword public 'BSS'
- XOB ends
- XO segment dword public 'BSS'
- XO ends
- XOE segment dword public 'BSS'
- XOE ends
- endif
-
- if OMF
- ifdef DOS386
- HUGE_BSS segment dword public 'HUGE_BSS'
- HUGE_BSS ends
- endif
-
- EEND segment dword public 'ENDBSS'
- EEND ends
-
- ifdef DOS386
- STACK segment para stack 'STACK'
- STACK ends
-
- DGROUP group _DATA,XIFCB,XIFU,XIFL,XIFM,XIFCE,XOB,XO,XOE,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS,EEND,STACK
- else
- ifdef __OS2__
- STACK segment para stack 'STACK'
- STACK ends
-
- DGROUP group _DATA,XIFCB,XIFU,XIFL,XIFM,XIFCE,XOB,XO,XOE,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS,EEND,STACK
- else
- ifdef __NT__
- STACK segment para stack 'STACK'
- STACK ends
-
- DGROUP group _DATA,XIFCB,XIFU,XIFL,XIFM,XIFCE,XOB,XO,XOE,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS,EEND,STACK
- else
- DGROUP group _DATA,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS,EEND
- endif ;__NT__
-
- endif ;__OS2__
- endif ;DOS386
-
- else ;OMF
- if OMF
- DGROUP group _DATA,XIFCB,XIFU,XIFL,XIFM,XIFCE,XOB,XO,XOE,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS
- else
- DGROUP group _DATA,_BSS
- endif
- endif
- endif
-
- _DATA segment
- if _FLAT
- assume DS:FLAT
- else
- assume DS:DGROUP
- endif
- endm
-
- enddata macro
- _DATA ends
- endm
-
- P equ 8 ; Offset of start of parameters on the stack frame
- ; From EBP assuming EBP was pushed.
- PS equ 4 ; Offset of start of parameters on the stack frame
-
- ; From ESP assuming EBP was NOT pushed.
- ;; For Win32, ESeqDS should be TRUE
- ifdef _WIN32
- ESeqDS equ 1
- else
- ESeqDS equ 0
- endif
-
- FSeqDS equ 0
- GSeqDS equ 0
- SSeqDS equ 1
- SIZEPTR equ 4 ; Size of a pointer
- LPTR equ 0
- SPTR equ 1
- LCODE equ 0
-
- func macro name
- _&name proc near
- ifndef name
- name equ _&name
- endif
- endm
-
- callm macro name
- call _&name
- endm
-
- ;Macros to replace public, extrn, and endp for C-callable assembly routines,
- ; and to define labels: c_label defines labels,
- ; c_public replaces public, c_extrn replaces extrn, and c_endp replaces endp
-
- c_name macro name
- name equ _&name
- endm
-
- c_label macro name
- _&name:
- endm
-
- c_public macro a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
- ifnb <a> ;;Check for blank argument
- public _&a
- a equ _&a
- ifnb <b>
- c_public b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
- endif
- endif
- endm
-
- c_extrn macro a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
- ifnb <a> ;;Check for blank argument
- extrn _&a:b
- a equ _&a
- ifnb <c>
- c_extrn c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
- endif
- endif
- endm
-
-
- c_endp macro name
- _&name ENDP
- endm
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Define function ctor as a static constructor
- static_ctor macro ctor
- ifndef _NOCTOR
- if 1
- XIFCB segment dword public 'DATA'
- XIFCB ends
- XIFU segment dword public 'DATA'
- ;dd ctor
- XIFU ends
- XIFL segment dword public 'DATA'
- ;dd ctor
- XIFL ends
- XIFM segment dword public 'DATA'
- if _FLAT
- dd offset FLAT:ctor
- else
- dd ctor
- endif
- XIFM ends
- XIFCE segment dword public 'DATA'
- XIFCE ends
- else
- XIB segment dword public 'DATA'
- XIB ends
- XI segment dword public 'DATA'
- if _FLAT
- dd offset FLAT:ctor
- else
- dd ctor
- endif
- XI ends
- XIE segment dword public 'DATA'
- XIE ends
- endif
- endif
- endm
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Define function dtor as a static destructor
- static_dtor macro dtor
- ifndef _NOCTOR
- if 1
- XOB segment dword public 'DATA'
- XOB ends
- XO segment dword public 'DATA'
- if _FLAT
- dd offset FLAT:dtor
- else
- dd dtor
- endif
- XO ends
- XOE segment dword public 'DATA'
- XOE ends
- else
- XCB segment dword public 'DATA'
- XCB ends
- XC segment dword public 'DATA'
- if _FLAT
- dd offset FLAT:dtor
- else
- dd dtor
- endif
-
- XC ends
- XCE segment dword public 'DATA'
- XCE ends
- endif
- endif
- endm
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Other more or less useful macros
-
- ;Aligns the code on dword boundary for max speed.
- _align macro
- ;MASM 6.0 has a bug where ALIGN 4 produces bogus code when
- ;2 or 3 bytes of filler are necessary.
- ifdef @Version
- if @Version eq 600
- if 0
- if (($ - _TEXT) and 3) eq 1
- db 08Bh,0C0h ;MOV EAX,EAX
- nop
- else
- if (($ - _TEXT) and 3) eq 2
- db 08Bh,0C0h ;MOV EAX,EAX
- else
- if (($ - _TEXT) and 3) eq 3
- nop
- endif
- endif
- endif
- endif
- else
- align 4 ;for MASM 5.1
- endif
- else
- align 4 ;for 386ASM
- endif
- endm
-
- _push macro list
- irp arg,<list>
- push arg
- endm
- endm
-
- _pop macro list
- irp arg,<list>
- pop arg
- endm
- endm
-
- _if macro arg1,cond,arg2,lbl
- cmp arg1,arg2
- j&cond lbl
- endm
-
- _ifs macro arg1,cond,arg2,lbl
- cmp arg1,arg2
- j&cond short lbl
- endm
-
- clr macro list ;clear a register
- irp reg,<list>
- xor reg,reg
- endm
- endm
-
- jmps macro lbl
- jmp short lbl
- endm
-
- tst macro reg
- test reg,reg
- endm
-
- ifndef nobdos
-
- ifdef DOS386
- bdos macro func ;DOS system call.
- ifnb <func>
- mov AH,func
- endif
- int 21h
- endm
- endif ;DOS386
-
- ifdef X386
- bdos macro func ;DOS system call.
- ifnb <func>
- mov AH,func
- endif
- int 21h
- endm
- endif ;DOS386
-
- ifdef M_XENIX
- bdos macro func ; 386 XENIX system call.
- ifnb <func>
- mov EAX,func
- endif
-
- db 9ah ; call far 0x7:0
- dd 0
- dw 07h
- endm
- endif ;M_XENIX
-
- ifdef M_UNIX
- bdos macro func ; UNIX system call.
- ifnb <func>
- mov EAX,func
- endif
-
- db 9ah ; call far 0x7:0
- dd 0
- dw 07h
- endm
- endif ;M_UNIX
-
- endif ;nobdos
-
- _retf macro val ;force assembler to build a far return
- ifnb <val>
- db 0CAh
- dw val
- else
- db 0CBh
- endif
- endm
-
- _ret macro val ;decide whether caller or callee cleans stack
- if _STDCALL
- ret val
- else
- ret
- endif
- endm
-
- ; Macros to save and restore regs destroyed by a function
- ; Give the macro the list of registers used by the function:
- ; uses <AX,BX,SI,DI>
- ;
- ; At exit to function use 'unuse':
- ; unuse <DI,SI,BX,AX>
-
- uses macro list
- irp reg,<list>
- ifidn <reg>,<ebx> ;Save ebx.
- push reg
- endif
-
- ifidn <reg>,<EBX> ;Save EBX (bug in ifidni).
- push reg
- endif
-
- ifidn <reg>,<esi> ;Save esi.
- push reg
- endif
-
- ifidn <reg>,<ESI>
- push reg
- endif
-
- ifidn <reg>,<edi> ;Save edi.
- push reg
- endif
-
- ifidn <reg>,<EDI>
- push reg
- endif
-
- ifidn <reg>,<bx> ;Save bx.
- push reg
- endif
-
- ifidn <reg>,<BX>
- push reg
- endif
-
- ifidn <reg>,<si> ;Save si.
- push reg
- endif
-
- ifidn <reg>,<SI>
- push reg
- endif
-
- ifidn <reg>,<di> ;Save di.
- push reg
- endif
-
- ifidn <reg>,<DI>
- push reg
- endif
-
- ifidn <reg>,<ds> ;Save ds.
- push reg
- endif
-
- ifidn <reg>,<DS>
- push reg
- endif
-
- ifidn <reg>,<es> ;Save es.
- push reg
- endif
-
- ifidn <reg>,<ES>
- push reg
- endif
- endm
- endm
-
- unuse macro list
- irp reg,<list>
- ifidn <reg>,<ebx> ;Restore ebx.
- pop reg
- endif
-
- ifidn <reg>,<EBX>
- pop reg
- endif
-
- ifidn <reg>,<esi> ;Restore esi.
- pop reg
- endif
-
- ifidn <reg>,<ESI>
- pop reg
- endif
-
- ifidn <reg>,<edi> ;Restore edi.
- pop reg
- endif
-
- ifidn <reg>,<EDI>
- pop reg
- endif
-
- ifidn <reg>,<bx> ;Restore bx.
- pop reg
- endif
-
- ifidn <reg>,<BX>
- pop reg
- endif
-
- ifidn <reg>,<si> ;Restore si.
- pop reg
- endif
-
- ifidn <reg>,<SI>
- pop reg
- endif
-
- ifidn <reg>,<di> ;Restore di.
- pop reg
- endif
-
- ifidn <reg>,<DI>
- pop reg
- endif
-
- ifidn <reg>,<ds> ;Restore ds.
- pop reg
- endif
-
- ifidn <reg>,<DS>
- pop reg
- endif
-
- ifidn <reg>,<es> ;Restore es.
- pop reg
- endif
-
- ifidn <reg>,<ES>
- pop reg
- endif
-
- endm
- endm
-
-
- endif ;M_I386
-
- ; Executable type
- EXE_DOS equ 1 ; MSDOS
- EXE_DOS16RM equ 2 ; Rational 286 DOS Extender
- EXE_ZPM equ 4 ; ZPM 286 DOS Extender
- EXE_PHAR386 equ 8 ; Pharlap 386 DOS Extender
- EXE_DOSX equ 010h ; DOSX 386 DOS Extender
- EXE_WINDOWS equ 020h ; Windows 3
- EXE_OS2 equ 040h ; OS/2 1.x
- EXE_SCOUNIX equ 080h ; SCO Unix
- EXE_OS2_2 equ 100h ; OS/2 2.0
- EXE_WINDOWSNT equ 200h ; Windows NT
-
-